package matching_algorithms;

//
//package matchingAlgorithms;
//
//import com.google.ortools.flow.MinCostFlow;
//import com.google.ortools.flow.StarGraph;
//
//import com.jme3.math.Vector3f;
//import java.util.ArrayList;
//import camera.AbstractCamera;
//
///**
// *
// * @author nancy
// */
//
//// or-tools must be installed for this to work
//
//public class ORToolsMatching extends AbstractMatching {
//    static {
//        System.loadLibrary("jniflow");
//    }
//    
//    public int[] match(float[][] distancesFloat) {
//        int numCameras = distancesFloat.length;
//        int numSubjects = distancesFloat[0].length;
//        
//        // Convert distances from float to int
//        int[][] distances = new int[numCameras][numSubjects];
//        for (int i = 0; i < numCameras; ++i) {
//            for (int j = 0; j < numSubjects; ++j) {
//                distances[i][j] = (int)distancesFloat[i][j];
//            }
//        }
//        
//        int maxNumArcs = numCameras * numSubjects 
//                + numCameras + numSubjects + 1;
//        StarGraph graph_ = new StarGraph
//                (numCameras + numSubjects + 2, maxNumArcs);
//        MinCostFlow flow = new MinCostFlow(graph_);
//        
//        int sourceIndex = numCameras + numSubjects;
//        int targetIndex = numCameras + numSubjects + 1;
//        
//        // 0...numCameras - 1 are the indices of the camera nodes
//        // numCameras...numCameras + numSubjects - 1 
//        // are the indices of the subject nodes
//        for (int i = 0; i < numCameras; ++i) {
//            long arcIndex = graph_.addArc(sourceIndex, i);
//            flow.setArcUnitCost(arcIndex, 0);
//            flow.setArcCapacity(arcIndex, 1);
//        }
//        for (int i = numCameras; i < numCameras + numSubjects; ++i) {
//            long arcIndex = graph_.addArc(i, targetIndex);
//            flow.setArcUnitCost(arcIndex, 0);
//            flow.setArcCapacity(arcIndex, 1);
//        }
//        for (int camera = 0; camera < numCameras; ++camera) {
//            for (int subject = numCameras;
//                 subject < numCameras + numSubjects;
//                 ++subject) {
//                long arcIndex = graph_.addArc(camera, subject);
//                flow.setArcUnitCost
//                        (arcIndex, distances[camera][subject-numCameras]);
//                flow.setArcCapacity(arcIndex, 1);
//            }
//        }
//        
//        // Turning the problem into the minimum circulation problem
//        // which is equivalent to the minimum-cost maximum-flow problem
//        long tsArc = graph_.addArc(targetIndex, sourceIndex);
//        flow.setArcUnitCost(tsArc, Integer.MIN_VALUE);
//        flow.setArcCapacity(tsArc, Integer.MAX_VALUE);
//        
//        // An unmatched camera is denoted by -1 in the result array
//        int[] result = new int[numCameras];
//        for (int i = 0; i < numCameras; ++i) result[i] = -1;
//        if (flow.solve()) {
//            for (int camera = 0; camera < numCameras; ++camera) {
//                for (int subject = numCameras;
//                    subject < numCameras + numSubjects;
//                    ++subject) {
//                    int arcIndex = numCameras + numSubjects
//                            + (camera*numSubjects) + subject - numCameras;
//                    if (flow.flow(arcIndex) == 1) {
//                        result[camera] = subject - numCameras;
//                    }
//                }
//            }
//        } else {
//            System.out.println("No solution found");
//        }
//        return result;
//    }
//    
//    @Override
//    public float[][]buildGraph(ArrayList<AbstractCamera> cameras,
//            ArrayList<Vector3f> positions,
//            boolean [][] isMatched) {
//        float[][] distances = new float[cameras.size()][positions.size()];
//        for (int i = 0; i < cameras.size(); i++) {
//            for (int j = 0; j < positions.size(); j++) {
//                distances[i][j] = (isMatched[i][j])? 
//                        cameras.get(i).getCam().getLocation().
//                          distance(positions.get(j))*100 
//                        : (1 << 30);
//            }
//        }
//        return distances;
//    }
//}
